function result = plexIntTrialResult(timeRange)
% Compute a trial result for the Snow Dots plexonIntegration demo.
%
%   plexIntTrialResult() uses topsDataLog to compute correct/incorrect
%   trial results online, during the Snow Dots plexonIntegration demo.  It
%   expects be called by a dotsComputableFunction object on the server-side
%   of dotsTheComputablesManager (i.e. on the Plexon machine), which in
%   turn is invoked by a counterpart object on the Snow Dots client-size.
%
%   Note: trial results could just as well be computed on the client side,
%   and need not use dotsTheComputablesManager at all.  But for
%   demonstration purposes, the plexonIntegration demo computes the results
%   with the dotsTheComputablesManager server, which might be running on a
%   separate machine!
%
%   In principle, plexIntTrialResult() could access data with the Plexon
%   Matlab client SDK, and use analog and spike data to compute each trial
%   result.
%
%   The behavior of plexIntTrialResult() is specific to the Snow Dots
%   plexonIntegration demo:
%       - it expectes that dotsTheComputablesManager is receiving regular
%       topsDataLog updates, so that the server-side data log matches the
%       client-side data log (i.e., it knows what's going on on the client
%       side).
%       - it expects that topsDataLog contains data for the random dot
%       motion direction from each trial.
%       - it expects that topsDataLog may or may not contain data for a
%       subject response on each trial.
%       - it compares motion direction and subject first response and
%       returns "correct", "incorrect", or "no choice", to the client side.
%
%   The timeRange argument is used to select data from topsDataLog specific
%   to the current trial.  It should have the form [laterThan asLateAs], in
%   the same units and time frame as the clockFunction of the client-side
%   topsDataLog.
%
%   plexIntTrialResult() always returns one of the results "correct",
%   "incorrect", or "no choice", or "error" if there was an internal
%   problem on the server side.
%

result = 'error';
try
    % can't remember the actual name of the topsDataLog droup that
    % contains left-right conditions and responses.  So search for them
    % with partial names.  Note that ".*" is a multi-character wildcard.
    log = topsDataLog.theDataLog;
    conditionGroup = ...
        log.getGroupNamesMatchingExpression('left.*right.*Value');
    choiceGroup = ...
        log.getGroupNamesMatchingExpression('Query.*output');
    
    % To access "currentDirection" I need to know the topsConditions
    % "paremeter" name ("direction") and the way in which
    % topsConditions/topsRunnable logs data (in a struct with a field
    % called "actionData").  This is cumbersome.  See Snow Dots issue
    % 50.
    allConditions = log.getAllItemsFromGroup(conditionGroup{1});
    currentCondition = allConditions{end};
    currentDirection = currentCondition.actionData.direction;
    
    result = 'no choice';
    if nargin > 0 && all(isnumeric(timeRange)) && ~isempty(choiceGroup)
        currentData = topsDataLog.getSortedDataStruct(timeRange);
        if numel(currentData) > 0
            firstChoice = ...
                find(strcmp({currentData.group}, choiceGroup), 1, 'first');
            choiceDirection = currentData(firstChoice).item;
            
            if choiceDirection == currentDirection
                result = 'correct';
            else
                result = 'incorrect';
            end
        end
    end
catch err
    disp(err)
end